package xcache

import (
	"crypto/md5"
	"encoding/json"
	"fmt"
	"sort"
	"strings"
)

// 生成CacheKey下标
// 增强模式，针对多维map进行order排序、string拼接、MD5生成的方式进行保持一致
//
//	args	任意类型参数，用于进行MD5加密，返回缓存下标信息
func Key(args ...any) CacheKey {
	a := ""
	for i := 0; i < len(args); i++ {
		a += key_enh(args[i], "")
	}
	a = strings.ReplaceAll(strings.TrimSpace(strings.ReplaceAll(a, "=[ ", "=[")), " ", "&")
	a = strings.ReplaceAll(a, "__default__=", "")
	if len(a) <= 32 {
		return CacheKey(strings.ReplaceAll(a, ":", "."))
	}
	return CacheKey(fmt.Sprintf("%X", md5.Sum([]byte(a))))
}

// 根据类型进行数值映射
//
//	args	待效验参数
//	keys	参数名
func key_enh(args any, keys string) string {
	if keys == "" {
		keys = "__default__"
	}
	ret := ""
	switch t := args.(type) {
	case int8, int16, int32, int, int64, uint8, uint16, uint32, uint64, uint:
		ret += fmt.Sprintf(" %s=%d", keys, t)
	case float32, float64:
		ret += fmt.Sprintf(" %s=%g", keys, t)
	case string, []byte, []rune:
		ret += fmt.Sprintf(" %s=%s", keys, t)
	default:
		ot := map[string]any{}
		any2any(args, &ot)
		order_sn := []string{}
		for i := range ot {
			order_sn = append(order_sn, i)
		}
		sort.Strings(order_sn)
		ret += " " + keys + "=["
		for i := 0; i < len(order_sn); i++ {
			ret += key_enh(ot[order_sn[i]], order_sn[i])
		}
		ret += "]"
	}
	return ret
}

// 通过JSON形式将类型转换
//
//	in	输入的类型
//	out	输出的类型
func any2any(in, out any) error {
	b, err := json.Marshal(in)
	if err != nil {
		return err
	}
	err = json.Unmarshal(b, out)
	if err != nil {
		return err
	}
	return nil
}
